; -- InstallVSCodeAfterReady.iss --
;
; This script checks if VSCode is installed, and if not, downloads and installs it.
; The detection and download happen after the "Ready to Install" page.

[Setup]
AppName=DevStar IDE Desktop
AppVersion=1.0
WizardStyle=modern
DefaultDirName={autopf}\DevStar IDE Desktop
DefaultGroupName=DevStar IDE Desktop
UninstallDisplayIcon={app}\DevStar IDE Desktop.exe
OutputDir=installer\
ArchitecturesAllowed=x64
ArchitecturesInstallIn64BitMode=x64

[Files]
; Place any regular files here
Source: "starter.ps1"; DestDir: "{src}";
Source: "devcontainer installer.bat"; DestDir: {tmp}; Flags:dontcopy;

[Icons]
Name: "{group}\VSCodeInstaller"; Filename: "{app}\DevStar IDE Desktop.exe"

[Code]
var
  DownloadPage: TDownloadWizardPage;
  VSCodeInstalled: Boolean;
  SubKeyNames: TArrayOfString;
  DisplayName : String;
  CustomPage : TWizardPage;
  i: Integer;
  OutputProgressWizardPage: TOutputProgressWizardPage;
  
function  ExitProcess(exitCode: integer): Integer; 
  external 'ExitProcess@kernel32.dll stdcall';

function IsProgramInstalled: Boolean;

begin
if RegGetSubkeyNames(HKLM, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\', SubKeyNames) then
for i := 0 to GetArrayLength(SubKeyNames)-1 do
  begin
  RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\' + SubKeyNames[i], 'DisplayName', DisplayName);
  //Log(Format('%s',[DisplayName]));
  //Log(Format('%d',[DisplayName = 'DevStar IDE Desktop'])); 
  if (DisplayName = 'DevStar IDE Desktop') then Result := True;
  end;

if RegGetSubkeyNames(HKCU, 'Software\Microsoft\Windows\CurrentVersion\Uninstall\', SubKeyNames) then
for i := 0 to GetArrayLength(SubKeyNames)-1 do
  begin
  //Log(Format('%s',[SubKeyNames[i]]));
  RegQueryStringValue(HKCU, 'Software\Microsoft\Windows\CurrentVersion\Uninstall\' + SubKeyNames[i], 'DisplayName', DisplayName);
  //Log(Format('%d',[DisplayName = 'Microsoft Visual Studio Code']));
  if (DisplayName = 'DevStar IDE Desktop') then Result := True;
  end;

end;
function IsVSCodeInstalled: Boolean;
begin
if RegGetSubkeyNames(HKLM, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\', SubKeyNames) then
for i := 0 to GetArrayLength(SubKeyNames)-1 do
  begin
  RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\' + SubKeyNames[i], 'DisplayName', DisplayName);
  //Log(Format('%s',[DisplayName]));
  //Log(Format('%d',[DisplayName = 'Microsoft Visual Studio Code'])); 
  if (DisplayName = 'Microsoft Visual Studio Code') then Result := True;
  end;

if RegGetSubkeyNames(HKCU, 'Software\Microsoft\Windows\CurrentVersion\Uninstall\', SubKeyNames) then
for i := 0 to GetArrayLength(SubKeyNames)-1 do
  begin
  //Log(Format('%s',[SubKeyNames[i]]));
  RegQueryStringValue(HKCU, 'Software\Microsoft\Windows\CurrentVersion\Uninstall\' + SubKeyNames[i], 'DisplayName', DisplayName);
  //Log(Format('%d',[DisplayName = 'Microsoft Visual Studio Code']));
  if (DisplayName = 'Microsoft Visual Studio Code') then Result := True;
  end;
end;

function OnDownloadProgress(const Url, FileName: String; const Progress, ProgressMax: Int64): Boolean;
begin
  { Update the log with download progress }
  Log(Format('Downloading %s: %d%% completed.', [FileName, (Progress * 100) div ProgressMax]));
  Result := True;
end;

function InstallDevContainerExtension: Boolean;
var
  ExecResult: Integer;
begin

  Log('Installing devcontainer extension...');
  { 使用 VSCode CLI 安装 devcontainer 扩展 }
  Exec(ExpandConstant('{tmp}\devcontainer installer.bat'), '', '', SW_HIDE, ewWaitUntilTerminated, ExecResult);
  Log(Format('%d',[ExecResult]));
  if ExecResult = 0 then
  begin
    Log('devcontainer extension installed successfully.');
    Result := True;
  end
  else
  begin
    Log('Failed to install devcontainer extension.');
    Result := False;
  end;
end;


function IsNpmInstalled: Boolean;
var
  ExecResult: Integer;
  Output: String;
begin
  { 使用命令行检查是否安装了 npm }
  Exec('cmd.exe', '/C npm -v', '', SW_HIDE, ewWaitUntilTerminated, ExecResult);
  Log(Format('%d',[ExecResult]));
  if ExecResult = 0 then
  begin
    { 如果返回码为0，表示 npm 已安装 }
    Result := True;
  end
  else
  begin
    { 如果执行 npm -v 失败，表示 npm 未安装 }
    Result := False;
  end;
end;

function InstallNpm: Boolean;
var
  NodeJsInstallerPath: String;
  ExecResult: Integer;
begin
  Log('npm not found, installing Node.js...');
  
  { 下载 Node.js 安装包并进行安装，npm 随 Node.js 一起安装 }
  DownloadPage := CreateDownloadPage(
    'Downloading Node.js for npm',
    'The installer is downloading Node.js. Please wait...',
    @OnDownloadProgress
  );
  DownloadPage.Clear;
  DownloadPage.Add('https://nodejs.org/dist/latest/node-v18.17.1-x64.msi', 'NodeJsInstaller.msi', '');
  DownloadPage.Show;

  try
    DownloadPage.Download; { 下载 Node.js 安装包 }
    NodeJsInstallerPath := ExpandConstant('{tmp}\NodeJsInstaller.msi');

    if FileExists(NodeJsInstallerPath) then
    begin
      Log('Starting installation of Node.js...');
      Exec(NodeJsInstallerPath, '', '', SW_SHOW, ewWaitUntilTerminated, ExecResult);

      if ExecResult = 0 then
      begin
        MsgBox('Node.js and npm have been successfully installed!', mbInformation, MB_OK);
        Result := True;
      end
      else
      begin
        MsgBox('Node.js installation failed with exit code: ' + IntToStr(ExecResult), mbCriticalError, MB_OK);
        Result := False; { 安装失败，停止安装过程 }
      end;
    end
    else
    begin
      MsgBox('Download failed. Please check your internet connection and try again.', mbCriticalError, MB_OK);
      Result := False; { 下载失败，停止安装过程 }
    end;
  finally
    DownloadPage.Hide;
  end;
end;

function InstallDevcontainerCLI: Boolean;
var
  ExecResult: Integer;
  IsInstalled: Boolean;
begin
  Log('Checking if devcontainer CLI is installed...');

  { 使用 npm 检查 devcontainer CLI 是否已经安装 }
  Exec('cmd.exe', '/C npm list -g @devcontainers/cli', '', SW_HIDE, ewWaitUntilTerminated, ExecResult);

  { 如果命令返回 0，说明 devcontainer CLI 已经安装 }
  if ExecResult = 0 then
  begin
    //MsgBox('devcontainer CLI is already installed!', mbInformation, MB_OK);
    Result := True;
    Exit;
  end
  else
  begin
    Log('devcontainer CLI is not installed. Proceeding with installation...');
  end;

  { 如果没有安装，使用 npm 安装 devcontainer CLI }
  Exec('cmd.exe', '/C npm install -g @devcontainers/cli', '', SW_HIDE, ewWaitUntilTerminated, ExecResult);

  if ExecResult = 0 then
  begin
    MsgBox('devcontainer CLI has been successfully installed!', mbInformation, MB_OK);
    Result := True;
  end
  else
  begin
    MsgBox('Failed to install devcontainer CLI. Exit code: ' + IntToStr(ExecResult), mbCriticalError, MB_OK);
    Result := False;
  end;
end;

function IsDockerInstalled: Boolean;
var
  ExecResult: Integer;
  Output: String;
begin
  // 尝试运行 "docker --version"，如果返回值为 0 则说明 Docker CLI 可用
  Result := Exec('cmd.exe', '/C docker --version', '', SW_HIDE, ewWaitUntilTerminated, ExecResult);
  Log(Format('%d',[ExecResult]));
end;

function ShouldSkipPage(PageID: Integer): Boolean;
begin
  Result := False;

  // 如果设置为跳过安装，跳过安装相关页面
  if not IsProgramInstalled then
  begin
    case PageID of
      wpSelectDir,      // 选择安装目录页面
      wpSelectComponents, // 选择组件页面
      wpSelectTasks,    // 选择附加任务页面
      wpReady,          // 准备安装页面
      wpInstalling:     // 正在安装页面
        Result := True; // 跳过这些页面
    end;
  end;
end;

//procedure CurPageChanged(CurPageID: Integer);
//begin
//  if CurPageID = CustomPage.ID then
 // begin
 //   WizardForm.NextButton.Caption := '启动'
 // end;
//end;
procedure InitializeWizard;
var
  
  InputQueryWizardPage: TInputQueryWizardPage;
  
  
  OutputMarqueeProgressWizardPage: TOutputMarqueeProgressWizardPage;
  AfterID: Integer;
begin
  Log(Format('%d已安装',[DisplayName = 'IsProgramInstalled'])); 
  if IsProgramInstalled then
  begin
    CustomPage := CreateCustomPage(wpWelcome, '您已安装自定义IDE', '点击下一步以启动开发环境');
  end
  else
  begin
    //CustomPage := CreateCustomPage(0, '您已安装自定义IDE', '点击下一步以启动开发环境');
  end;
  //AfterID := wpSelectTasks;
  VSCodeInstalled := IsVSCodeInstalled;
  ExtractTemporaryFile('devcontainer installer.bat');
  OutputMarqueeProgressWizardPage := CreateOutputMarqueeProgressPage('CreateOutputMarqueeProgressPage', 'ADescription');
  //InputQueryWizardPage := CreateInputQueryPage(wpReady, 'CreateInputQueryPage', 'ADescription', 'ASubCaption');
  //InputQueryWizardPage.Add('&APrompt:', False);
  //AfterID := InputQueryWizardPage.ID;
  
  OutputProgressWizardPage := CreateOutputProgressPage('检测依赖中', '');

end;



function NextButtonClick(CurPageID: Integer): Boolean;
var
  VSCodeInstallerPath: String;
  arg1 : String;
  ExecResult: Integer;
begin
  Result := True;
  //if (CurPageID = CustomPage.ID) then
  //begin
  //  arg1 := '-ExecutionPolicy Bypass -File "' + ExpandConstant('{src}\1.ps1') + '"';
  //  Log(Format('%s',[arg1]));
  //  Exec('powershell.exe', arg1, '', SW_SHOW, ewWaitUntilTerminated, ExecResult);
  //ExitProcess(1);
  //end;
  if (CurPageID = wpReady) then
  begin
    OutputProgressWizardPage.SetText('','正在检测Visual Studio Code');
    OutputProgressWizardPage.SetProgress(0, 100);
    OutputProgressWizardPage.Show;
    if not VSCodeInstalled then
    begin
      // 显示 VSCode 安装进度
      
      WizardForm.StatusLabel.Caption := 'Downloading Visual Studio Code...';
      DownloadPage := CreateDownloadPage(
        'Downloading Visual Studio Code',
        'The installer is downloading Visual Studio Code. Please wait...',
        @OnDownloadProgress
      );
      DownloadPage.Clear;
      DownloadPage.Add('https://update.code.visualstudio.com/latest/win32-x64/stable', 'VSCodeSetup.exe', '');
      DownloadPage.Show;
      
      try
        DownloadPage.Download;  // 开始下载 VSCode 安装包
        VSCodeInstallerPath := ExpandConstant('{tmp}\VSCodeSetup.exe');
        
        if FileExists(VSCodeInstallerPath) then
        begin
          WizardForm.StatusLabel.Caption := 'Installing Visual Studio Code...';
          Exec(VSCodeInstallerPath, '', '', SW_SHOW, ewWaitUntilTerminated, ExecResult);
          
          if ExecResult = 0 then
          begin
            //MsgBox('Visual Studio Code has been successfully installed!', mbInformation, MB_OK);
            VSCodeInstalled := True;
          end
          else
          begin
            MsgBox('Installation failed with exit code: ' + IntToStr(ExecResult), mbCriticalError, MB_OK);
            Result := False; 
          end;
        end
        else
        begin
          MsgBox('Download failed. Please check your internet connection and try again.', mbCriticalError, MB_OK);
          Result := False; 
        end;
      finally
        DownloadPage.Hide;
      end;
    end
    else
    begin
      // 如果 VSCode 已安装，继续安装扩展
      OutputProgressWizardPage.SetProgress(20, 100);
      OutputProgressWizardPage.SetText('','正在检测安装devcontainer extension');
      OutputProgressWizardPage.Show;
      WizardForm.StatusLabel.Caption := 'Installing devcontainer extension...';
      if InstallDevContainerExtension then
      begin
        WizardForm.StatusLabel.Caption := 'devcontainer extension installed successfully.';
      end
      else
      begin
        WizardForm.StatusLabel.Caption := 'Failed to install devcontainer extension.';
        Result := False;
      end;
    end;
    // 检查并安装 npm
    OutputProgressWizardPage.SetProgress(40, 100);
    OutputProgressWizardPage.SetText('','正在检测安装npm');
    if not IsNpmInstalled then
    begin
      WizardForm.StatusLabel.Caption := 'Installing npm...';
      if InstallNpm then
      begin
        WizardForm.StatusLabel.Caption := 'npm installed successfully.';
        OutputProgressWizardPage.Hide;
      end
      else
      begin
        Result := False;
      end;
    end;
    OutputProgressWizardPage.SetProgress(60, 100);
    OutputProgressWizardPage.SetText('','正在检测devcontainer CLI是否安装');
    // 安装 devcontainer CLI
    if Result then
    begin
      
      WizardForm.StatusLabel.Caption := 'Installing devcontainer CLI...';
      if not InstallDevcontainerCLI then
      begin
        Result := False;
        WizardForm.StatusLabel.Caption := 'Failed to install devcontainer CLI.';
      end;
    end;
    OutputProgressWizardPage.SetProgress(80, 100);
    OutputProgressWizardPage.SetText('','正在检测docker desktop是否安装');
    if  IsDockerInstalled then
    begin 
    OutputProgressWizardPage.SetText('','docker desktop已正确安装');
    OutputProgressWizardPage.SetProgress(100, 100);
    Sleep(1000);
    end
    else begin
    Result := False;
    end;
    OutputProgressWizardPage.Hide;
  end;
end;


[Run]
; Run the PowerShell script after installation
//Filename: "powershell.exe"; Parameters: "-ExecutionPolicy Bypass -File ""{src}\1.ps1""";
